package com.hb.B_面向对象.A_类与继承

/**
 * kotlin中类声明的语法：
 *  1. 不可变属性成员：Kotlin支持用val在勒种声明引用不可变的属性成员，这是利用java中的final修饰符来实现的
 *      使用var声明的属性则反之引用可变
 *
 *  2. 属性默认值：因为java的属性都有默认值，比如int类型的默认值为0，引用类型的默认值为null，所以在声明
 *      属性的时候，我们不需要指定默认值。而在Kotlin中，除非显示的声明延迟初始化，不然就需要指定属性的默认值
 *
 *  3. 不同的可访问修饰符：Kotlin类中的成员默认是全局可见的（public），而Java的默认可见域包作用域，因此在java中，
 *      我们必须采用public修饰才能达到相同的效果。
 */
class Bird() : Flyer {
    override val speed = 100
    val weight: Double = 200.0
    val color: String = "blue"
    val age: Int = 1
    fun FLy() {
        //全局可见
    }

    override fun kind() {
        println("bird kind")
    }

}

/**
 * java8新特性中，接口中可以有默认方法的实现
 *      作用：使得我们在向接口中新增加方法的时候，之前继承过该接口的类则可以不需要实现这个新方法。
 *
 * Kotlin中如何声明一个接口：
 *
 *      通过反编译器是通过定义了一个静态内部类DefaultImpls来提供方法的默认实现的。同时Kotlin接口
 *      支持属性声明。然而他在java源码中是通过一个get方法来实现的。在接口中的属性并不能像Java接口
 *      那样，被直接赋值一个常量。
 *
public static final class DefaultImpls {
public static int getHeight(Flyer $this) {
return 1000;
}

public static void fly(Flyer $this) {
String str = "i can fly";
boolean bool = false;
System.out.println(str);
}
}
}
 */
interface Flyer {
    //抽象属性，不允许赋值
    val speed: Int
    //val height=1000; //错误，不支持初始化

    /**
     * Kotlin提供了另外一个方式来实现这种效果
     * Kotlin中的接口的属性背后其实是用方法来实现的，所以说如果我们要为变量赋值常量，那么久需要编译器
     * 原生就支持方法默认实现。但是Kotlin是基于java6的，当时并不支持这种特性，所以我们并不能像Java
     * 那样给接口的属性赋值一个常量。抽象属性和方法一样，若没有指定默认行为，则在实现接口的类找那个必须对该
     * 属性进行初始化。
     */
    //熟悉的默认实现,和方法的默认实现一样
    val height
        get() = 1000

    //抽象方法
    fun kind()

    //默认实现方法
    fun fly() {
        println("i can fly")
    }
}


fun main() {
    //kotlin中创建一个对象。
    /**
     * Kotlin中没有new关键字去创建对象。
     */
    //val bird = Bird()
}